// wifi_prov_manager.c  (解耦版本：不触碰 wifi_on/事件注册/默认模式设置，仅提供纯业务管理)
#include <string.h>
#include <stdio.h>
#include "app_config.h"
#include "system/includes.h"
#include "wifi/wifi_connect.h"
#include "lwip.h"
#include "dhcp_srv/dhcp_srv.h"

#include "wifi_prov_manager.h"

// ---------- 简易CRC ----------
static u32 prov_crc32(const void *data, u32 len)
{
    const u8 *p = (const u8 *)data;
    u32 c = 0xFFFFFFFF;
    for (u32 i = 0; i < len; i++)
    {
        c ^= p[i];
        for (int j = 0; j < 8; j++)
        {
            u32 m = -(c & 1);
            c = (c >> 1) ^ (0xEDB88320 & m);
        }
    }
    return ~c;
}

// ---------- 内部状态 ----------
typedef struct
{
    OS_MUTEX mtx;
    u8 inited;
    wifi_prov_nv_t nv;
    wifi_prov_desired_mode_t desired;
    wifi_prov_ops_t ops;
} prov_ctx_t;

static prov_ctx_t g;

// ---------- 日志 ----------
#define PLOG(fmt, ...)                               \
    do                                               \
    {                                                \
        if (g.ops.log)                               \
        {                                            \
            g.ops.log("[prov] " fmt, ##__VA_ARGS__); \
        }                                            \
        else                                         \
        {                                            \
            printf("[prov] " fmt, ##__VA_ARGS__);    \
        }                                            \
    } while (0)

// ---------- syscfg NV ----------
static int nv_default(wifi_prov_nv_t *nv)
{
    memset(nv, 0, sizeof(*nv));
    nv->magic = WIFI_PROV_MAGIC_NEED_PROV;
    nv->crc = prov_crc32(nv, sizeof(*nv) - 4);
    return 0;
}

int wifi_prov_nv_load(wifi_prov_nv_t *out)
{
    if (!out)
        return -1;
    wifi_prov_nv_t tmp;
    memset(&tmp, 0, sizeof(tmp));
    int r = syscfg_read(WIFI_PROV_CFG_ID, &tmp, sizeof(tmp));
    if (r != sizeof(tmp))
    {
        nv_default(&tmp);
        *out = tmp;
        return 1;
    }
    u32 crc = prov_crc32(&tmp, sizeof(tmp) - 4);
    if (crc != tmp.crc)
    {
        nv_default(&tmp);
        *out = tmp;
        return 2;
    }
    *out = tmp;
    return 0;
}

static int nv_save(const wifi_prov_nv_t *in)
{
    wifi_prov_nv_t tmp = *in;
    tmp.crc = prov_crc32(&tmp, sizeof(tmp) - 4);
    return (syscfg_write(WIFI_PROV_CFG_ID, &tmp, sizeof(tmp)) == sizeof(tmp)) ? 0 : -2;
}

static int nv_set_magic(u32 magic)
{
    wifi_prov_nv_t nv;
    wifi_prov_nv_load(&nv);
    nv.magic = magic;
    return nv_save(&nv);
}

int wifi_prov_set_final_sta_and_normal_boot(const char *ssid, const char *pwd)
{
    OS_MUTEX_PEND(&g.mtx, 0);
    wifi_prov_nv_t nv = g.nv;
    if (ssid)
        strncpy(nv.ssid, ssid, sizeof(nv.ssid) - 1);
    if (pwd)
        strncpy(nv.pwd, pwd, sizeof(nv.pwd) - 1);
    nv.magic = WIFI_PROV_MAGIC_NORMAL;
    int ret = nv_save(&nv);
    if (ret == 0)
        g.nv = nv;
    OS_MUTEX_POST(&g.mtx);
    return ret;
}

// ---------- 重启 ----------
void __attribute__((weak)) wifi_prov_reboot(void)
{
    extern void system_reset(void);
    system_reset();
}

static void do_reboot(void)
{
    if (g.ops.reboot)
        g.ops.reboot();
    else
        wifi_prov_reboot();
}

// ---------- SDK STA存储清理 ----------
static void sdk_clear_sta_info(void)
{
    // struct wifi_mode_info info = {0};
    // if (wifi_get_mode_stored_info(&info) == 0)
    // {
    //     wifi_del_stored_sta_info();
    // }
}

// ---------- 决策 desired 模式 ----------
static void decide_desired_locked(void)
{
    if (g.nv.magic == WIFI_PROV_MAGIC_FACTORY)
    {
        PLOG("factory\n");
        sdk_clear_sta_info();
        nv_default(&g.nv);
        nv_save(&g.nv); // 置 NEED_PROV
    }
    g.desired = (g.nv.magic == WIFI_PROV_MAGIC_NEED_PROV) ? WIFI_PROV_DESIRED_AP : WIFI_PROV_DESIRED_STA;
}

// ---------- 公共API ----------
int wifi_prov_manager_init(const wifi_prov_ops_t *ops)
{
    if (!g.inited)
    {
        memset(&g, 0, sizeof(g));
        os_mutex_create(&g.mtx);
        g.inited = 1;
    }
    OS_MUTEX_PEND(&g.mtx, 0);
    if (ops)
        g.ops = *ops;
    else
        memset(&g.ops, 0, sizeof(g.ops));
    wifi_prov_nv_load(&g.nv);
    decide_desired_locked();
    OS_MUTEX_POST(&g.mtx);
    return 0;
}

wifi_prov_desired_mode_t wifi_prov_manager_get_desired_mode(void)
{
    OS_MUTEX_PEND(&g.mtx, 0);
    wifi_prov_desired_mode_t d = g.desired;
    OS_MUTEX_POST(&g.mtx);
    return d;
}

int wifi_prov_manager_on_event(enum WIFI_EVENT event, void *arg)
{
    switch (event)
    {
        case WIFI_EVENT_MODULE_INIT:
            {
                // 时机：上层在此事件里根据 get_desired_mode 设置默认模式
                OS_MUTEX_PEND(&g.mtx, 0);
                if (g.desired == WIFI_PROV_DESIRED_STA)
                {
                    // 对齐SDK存储（可选）
                    if (g.nv.ssid[0] && g.ops.store_sta_info)
                    {
                        g.ops.store_sta_info(g.nv.ssid, g.nv.pwd);
                    }
                }
                OS_MUTEX_POST(&g.mtx);
                break;
            }
        case WIFI_EVENT_AP_START:
            // AP已启动：由上层注入的ops执行网络与服务器启动，模块不直接依赖实现
            if (g.ops.ap_net_init)
                g.ops.ap_net_init();
            if (g.ops.prov_server_start)
                g.ops.prov_server_start();
            break;
        case WIFI_EVENT_AP_STOP:
            if (g.ops.prov_server_stop)
                g.ops.prov_server_stop();
            break;
        // case WIFI_EVENT_STA_CONNECTED:
        // case WIFI_EVENT_STA_GOT_IP:
        case WIFI_EVENT_STA_DISCONNECT:
        default:
            break;
    }
    return 0;
}

int wifi_prov_manager_on_credentials(const char *ssid, const char *pwd, int save)
{
    PLOG("on_credentials ssid=%s save=%d\n", ssid ? ssid : "", save);
    if (save && g.ops.store_sta_info)
    {
        g.ops.store_sta_info(ssid ? ssid : "", pwd ? pwd : "");
    }
    wifi_prov_set_final_sta_and_normal_boot(ssid, pwd);
    if (g.ops.on_finished)
        g.ops.on_finished(0);
    // 留一点时间给HTTP回包等
    os_time_dly(50);
    do_reboot();
    return 0;
}

int wifi_prov_trigger_ap_and_reboot(void)
{
    if (nv_set_magic(WIFI_PROV_MAGIC_NEED_PROV) != 0)
        return -1;
    os_time_dly(10);
    do_reboot();
    return 0;
}

int wifi_prov_factory_reset_and_reboot(void)
{
    sdk_clear_sta_info();
    wifi_prov_nv_t nv;
    nv_default(&nv); // NEED_PROV
    nv_save(&nv);
    os_time_dly(10);
    do_reboot();
    return 0;
}